# Generated by Django 4.2.1 on 2023-09-05 19:24

from django.db import migrations


def build_input_fields_from_input_schema(input_schema, input_ui_schema):
    input_fields = []
    required_fields = input_schema['required'] if 'required' in input_schema else [
    ]
    for key in input_schema['properties']:
        input_field = {
            'name': key,
            'type': input_schema['properties'][key]['type'],
            'title': input_schema['properties'][key]['title'],
            'description': input_schema['properties'][key]['description'],
        }

        if 'default' in input_schema['properties'][key]:
            input_field['default'] = input_schema['properties'][key]['default']

        # Select options
        if 'enum' in input_schema['properties'][key] and 'enumNames' in input_schema['properties'][key]:
            input_field['type'] = 'select'
            input_field['options'] = [
                {
                    'label': input_schema['properties'][key]['enumNames'][i],
                    'value': input_schema['properties'][key]['enum'][i],
                } for i in range(len(input_schema['properties'][key]['enum']))
            ]

        if key in input_ui_schema:
            if 'ui:widget' in input_ui_schema[key]:
                if input_ui_schema[key]['ui:widget'] == 'file':
                    input_field['type'] = 'file'
                elif input_ui_schema[key]['ui:widget'] == 'textarea':
                    input_field['type'] = 'text'
                elif input_ui_schema[key]['ui:widget'] == 'radio':
                    input_field['type'] = 'boolean'
                elif input_ui_schema[key]['ui:widget'] == 'voice':
                    input_field['type'] = 'voice'

        if key in required_fields:
            input_field['required'] = True

        input_fields.append(input_field)

    if 'ui:order' in input_ui_schema:
        input_fields = sorted(
            input_fields,
            key=lambda x: input_ui_schema['ui:order'].index(
                x['name']))

    return input_fields


def build_processors_from_run_graph(run_graph):
    processors = []
    endpoints = [
        x.exit_endpoint for x in run_graph.all().order_by(
            'id',
        ) if x is not None and x.exit_endpoint is not None
    ]
    for endpoint, index in zip(endpoints, range(1, len(endpoints) + 1)):
        processor_obj = {
            'id': f'_input{index}',
            'processor_slug': endpoint.api_backend.slug,
            'provider_slug': endpoint.api_backend.api_provider.slug,
            'input': endpoint.input,
            'config': endpoint.config,
        }
        processors.append(processor_obj)
    return processors


def build_app_data_from_app(app):
    return {
        'name': app.name,
        'slug': app.name.lower().replace(
            ' ',
            '-'),
        'description': app.description,
        'type_slug': app.type.slug,
        'config': app.config,
        'input_fields': build_input_fields_from_input_schema(
            app.input_schema,
            app.input_ui_schema),
        'output_template': app.output_template,
        'processors': build_processors_from_run_graph(
            app.run_graph),
    }


class Migration(migrations.Migration):

    def create_app_data_from_app(apps, schema_editor):
        """
        Iterate through all apps, create processors from run_graph, input_fields from input_schema, input_ui_schema and save as app_data
        """
        App = apps.get_model('apps', 'App')
        AppData = apps.get_model('apps', 'AppData')

        apps = App.objects.all()
        for app in apps:
            app_data_obj = AppData.objects.filter(app_uuid=app.uuid).first()
            if not app_data_obj:
                try:
                    app_data = build_app_data_from_app(app)
                    # We make a non-draft version of the app_data if the app is
                    # published
                    if app.is_published:
                        AppData.objects.create(
                            app_uuid=app.uuid, data=app_data, is_draft=False
                        )
                    AppData.objects.create(
                        app_uuid=app.uuid,
                        data=app_data,
                        is_draft=True,
                        version=1 if app.is_published else 0)
                except Exception as e:
                    print(
                        f'Error creating app_data for app {app.name} - {str(app.uuid)}')
                    print(e)

    dependencies = [
        ('apps', '0003_appdata'),
        ('apiabstractor', '0003_rename_processor_slugs'),
    ]

    operations = [
        migrations.RunPython(create_app_data_from_app,
                             migrations.RunPython.noop),
    ]
